<template>
  <div class="tools" :class="theme">
    <span>主题</span>
    <select v-model="theme" @change="onSwitchTheme">
      <option value="vs-dark">vs-dark</option>
      <option value="vs">vs</option>
      <option value="hc-black">hc-black</option>
    </select>
    <span>语言</span>
    <select v-model="language" @change="onSwitchLanguage">
      <option>json</option>
      <option>sql</option>
      <option>yaml</option>
      <option>css</option>
      <option>javascript</option>
    </select>
    <button @click="onFormat">格式化</button>
    <button>拷贝</button>
  </div>
  <div ref="codeEditBox" class="codeEditBox"></div>
</template>
<script lang="ts">
import { defineComponent, onBeforeUnmount, onMounted, ref, watch } from "vue";
// import JsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
// import CssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker";
// import HtmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker";
// import TsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker";
// import EditorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker"

import { language as sqlLanguage } from "monaco-editor/esm/vs/basic-languages/sql/sql.js";
import { language as yamlLanguage } from "monaco-editor/esm/vs/basic-languages/yaml/yaml.js";
import "monaco-editor/esm/vs/basic-languages/sql/sql.contribution";

import "monaco-editor/esm/vs/editor/editor.all.js"
import "monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.js"

import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js"

export default defineComponent({
  name: "MonacoEditor",
  components: {},
  props: {
    value: {
      type: String,
      default: ""
    },
    language: {
      type: String,
      default: "json"
    }
  },
  emits: ["update:modelValue", "change", "editor-mounted"],
  setup(props, { emit }) {
    console.log(props);
    // (self as any).MonacoEnvironment = {
    //   getWorker(_: string, label: string) {
    //     if (label === "json") {
    //       return new JsonWorker();
    //     }
    //     if (["css", "scss", "less"].includes(label)) {
    //       return new CssWorker();
    //     }
    //     if (["html", "handlebars", "razor"].includes(label)) {
    //       return new HtmlWorker();
    //     }
    //     if (["typescript", "javascript"].includes(label)) {
    //       return new TsWorker();
    //     }
    //     return new EditorWorker();
    //   }
    // };
    let editor: any;
    const codeEditBox = ref();
    const language = ref(props.language || "json");
    const theme = ref("hc-black");
    const init = () => {
      console.log("初始化");
      // monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
      //   noSemanticValidation: true,
      //   noSyntaxValidation: false
      // });
      // monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
      //   target: monaco.languages.typescript.ScriptTarget.ES2020,
      //   allowNonTsExtensions: true
      // });
      monaco.languages.registerCompletionItemProvider("sql", {
        provideCompletionItems() {
          const suggestions: any = [];
          // 这个keywords就是sql.js文件中有的
          sqlLanguage.keywords.forEach((item: any) => {
            suggestions.push({
              label: item,
              kind: monaco.languages.CompletionItemKind.Keyword,
              insertText: item
            });
          });
          sqlLanguage.operators.forEach((item: any) => {
            suggestions.push({
              label: item,
              kind: monaco.languages.CompletionItemKind.Operator,
              insertText: item
            });
          });
          sqlLanguage.builtinFunctions.forEach((item: any) => {
            suggestions.push({
              label: item,
              kind: monaco.languages.CompletionItemKind.Function,
              insertText: item
            });
          });
          sqlLanguage.builtinVariables.forEach((item: any) => {
            suggestions.push({
              label: item,
              kind: monaco.languages.CompletionItemKind.Variable,
              insertText: item
            });
          });
          return {
            // 最后要返回一个数组
            suggestions
          };
        }
      });
      monaco.languages.registerCompletionItemProvider("yaml", {
        provideCompletionItems() {
          const suggestions: any = [];
          // 这个keywords就是python.js文件中有的
          yamlLanguage.keywords.forEach((item: any) => {
            suggestions.push({
              label: item,
              kind: monaco.languages.CompletionItemKind.Keyword,
              insertText: item
            });
          });
          return {
            // 最后要返回一个数组
            suggestions
          };
        }
      });
      console.log(codeEditBox);
      console.log(props.value);
      editor = monaco.editor.create(codeEditBox.value, {
        value: props.value || "", // 编辑器初始显示文字
        language: language.value, // 语言支持自行查阅demo
        automaticLayout: true, // 自适应布局
        theme: theme.value, // 官方自带三种主题vs, hc-black, or vs-dark
        foldingStrategy: "indentation",
        renderLineHighlight: "all", // 行亮
        selectOnLineNumbers: true, // 显示行号
        minimap: {
          enabled: false
        },
        readOnly: false, // 只读
        fontSize: 16, // 字体大小
        scrollBeyondLastLine: false, // 取消代码后面一大段空白
        overviewRulerBorder: false // 不要滚动条的边框
      });
      onFormat();
      // 监听值的变化
      editor.onDidChangeModelContent(() => {
        const value = editor.getValue(); // 给父组件实时返回最新文本
        emit("update:modelValue", value);
        emit("change", value);
      });
      emit("editor-mounted", editor);
    };
    watch(
      () => props.value,
      (newValue) => {
        if (editor) {
          const value = editor.getValue();
          if (newValue !== value) {
            editor.setValue(newValue);

          }
          onFormat();
        }
      }
    );
    const onSwitchTheme = () => {
      monaco.editor.setTheme(theme.value);
    };
    const onSwitchLanguage = () => {
      monaco.editor.setModelLanguage(editor.getModel()!, language.value);
    };
    const onFormat = () => {
      editor.getAction("editor.action.formatDocument").run();//自动格式化代码
    };
    watch(
      () => props.language,
      (newValue) => {
        monaco.editor.setModelLanguage(editor.getModel()!, newValue);
        language.value = newValue;
      }
    );

    onBeforeUnmount(() => {
      editor.dispose();
    });

    onMounted(() => {
      init();
    });

    // eslint-disable-next-line vue/no-dupe-keys
    return { codeEditBox, language, theme, onSwitchTheme, onFormat, onSwitchLanguage };
  }
});
</script>
<style lang="less" scoped>
.codeEditBox {
  width: 100%;
  flex: 1;
  min-height: 100px;
  height: 100%;
  overflow-y: auto;
}

.codeEditBox1 {
  height: calc(100% - 323px);
}

.tools {
  height: 20px;
  display: block;

  span {
    padding: 0 10px;
  }

  button {
    padding: 0 10px;
  }

  select {
    width: 120px;
    outline: none;
  }
}

.tools.vs-dark {
  background: #1f1f1f;
  border: none;
  border-bottom: 1px solid #323232;
  color: #cccccc;

  select {
    background: #1f1f1f;
  }

  button:hover {
    color: white;
  }
}
</style>
